#include "contactlistview.h"
#include "xmppmanager.h"
#include "contacttablemodel.h"
#include <QEvent>
#include <QSortFilterProxyModel>
#include <QHeaderView>
#include <iostream>
#include <stdexcept>
#include "chatwindow.h"
#include "messagesession.h"
#include <gloox/messagesession.h>

CUSTOM_EVENT_MAP(ContactListView) {
    CUSTOM_EVENT(EVENT_LOGIN, onLogin)
    CUSTOM_EVENT_WITH_PARAM(EVENT_LOGOFF, onLogoff, LogoffEvent, errorCode)
    CUSTOM_EVENT_WITH_PARAM(EVENT_CONTACT_INFO, onContactInfo, ContactEvent, contact)
    CUSTOM_EVENT_WITH_PARAM(EVENT_CONTACT_INFOS, onContactInfos, ContactsEvent, contacts)
    CUSTOM_EVENT_WITH_PARAM(EVENT_MESSAGE_SESSION, onMessageSession, MessageSessionEvent, session)
    CUSTOM_EVENT_WITH_PARAM(EVENT_CLOSE_CHAT_WINDOW, onCloseChatWindow, CloseChatWindowEvent, window)
}

int EVENT_CLOSE_CHAT_WINDOW;

ContactListView::ContactListView(QWidget *parent) :
    QTableView(parent)
{
    EVENT_CLOSE_CHAT_WINDOW = QEvent::registerEventType();
    XmppManager::instance().addLoginEventHandler(this);
    XmppManager::instance().addContactEventHandler(this);
    XmppManager::instance().addMessageSessionEventHandler(this);
    setVisible(false);
    table = new ContactTableModel(this);
    horizontalHeader()->setStretchLastSection(true);
    verticalHeader()->hide();
    horizontalHeader()->hide();
    setShowGrid(false);


    setEditTriggers(QAbstractItemView::NoEditTriggers);
    setSelectionMode(QAbstractItemView::SingleSelection);
    //setSortingEnabled(true);
    setSelectionBehavior(QAbstractItemView::SelectRows);

     proxyModel = new QSortFilterProxyModel(this);
    proxyModel->setSourceModel(table);
    proxyModel->setDynamicSortFilter(true);

    setModel(proxyModel);

    //QString newStr = QString("^[%1].*").arg("ABC");

    //proxyModel->setFilterRegExp(QRegExp(newStr, Qt::CaseInsensitive));
    //proxyModel->setFilterKeyColumn(0);
//    proxyModel->sort(1, Qt::AscendingOrder);
    setColumnWidth(0, 42);
    setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
 //   connect(selectionModel(),
 //           SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
 //           this, SIGNAL(selectionChanged(const QItemSelection &)));

    bool bret = connect(this,
            SIGNAL(doubleClicked(const QModelIndex &)),
            this, SLOT(onDoubleClicked(const QModelIndex &)));

    if (!bret)
    {
        std::clog << "connect doubleClicked and onDoubleClicked failed" << std::endl;
    }

    item = new ContactItemDelegate(this);
    setItemDelegate(item);
}

ContactListView::~ContactListView()
{
    XmppManager::instance().removeLoginEventHandler(this);
    XmppManager::instance().removeContactEventHandler(this);
    XmppManager::instance().removeMessageSessionEventHandler(this);
}

void ContactListView::onDoubleClicked ( const QModelIndex & index )
{


    ChatWindow chatWindow;
    QModelIndex imageIndex = index.sibling(index.row(), 0);

    ContactItem item = model()->data(imageIndex, KeyRole).value<ContactItem>();

    chatWindow.SetContactItem(item);
    if (chatWindowList.contains(chatWindow))
    {
        int nIndex = chatWindowList.indexOf(chatWindow);
        if (chatWindowList[nIndex].isVisible())
        {
            chatWindowList[nIndex].activateWindow();
            return;
        }
        chatWindowList.removeAt(nIndex);
    }

    std::string jid = item.jid();
    gloox::MessageSession* glooxSession = XmppManager::instance().createSession(jid);

    chatWindowList.append(chatWindow);
    chatWindowList.last().setSession(new MessageSession(glooxSession));
    chatWindowList.last().setEventHandler(this);
    chatWindowList.last().show();
    std::clog << "doubleclicked:" << index.column() << ":" << index.row() << std::endl;
}


void ContactListView::onLogin()
{
    setVisible(true);
}

void ContactListView::onLogoff(int errorCode)
{
    setVisible(false);
}

void ContactListView::onContactInfo(ContactItem& contact)
{
    table->updateRow(contact);
    if (!contact.vcard())
    {
        QString jid(contact.jid().c_str());
        XmppManager::instance().requestVcard(jid);
    }
}

void ContactListView::onContactInfos(std::vector<ContactItem>& contacts)
{
    for (std::vector<ContactItem>::iterator it = contacts.begin(); it != contacts.end(); it++)
    {
        onContactInfo(*it);
    }
}

void ContactListView::onMessageSession(gloox::MessageSession* session)
{
    ChatWindow chatWindow;
    chatWindow.SetContactItem(table->findContact(session->target().bare().c_str()));
    chatWindowList.append(chatWindow);
    chatWindowList.last().setSession(new MessageSession(session));
    chatWindowList.last().setEventHandler(this);

    chatWindowList.last().show();

}

void ContactListView::onCloseChatWindow(ChatWindow& window)
{
    int index = chatWindowList.indexOf(window);
    chatWindowList.removeAt(index);
}

